package com.topnav.mc.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.js.lib.result.Result;
import com.topnav.mc.admin.bean.CountChannelBean;
import com.topnav.mc.admin.bean.OrgDeviceBean;
import com.topnav.mc.admin.dao.mapper.DeviceChannelMapper;
import com.topnav.mc.admin.dao.mapper.DeviceMapper;
import com.topnav.mc.admin.entity.Device;
import com.topnav.mc.admin.entity.DeviceChannel;
import com.topnav.mc.admin.entity.GbServer;
import com.topnav.mc.admin.entity.Organization;
import com.topnav.mc.admin.entity.bean.DeviceBean;
import com.topnav.mc.admin.entity.bean.DeviceChannelBean;
import com.topnav.mc.admin.entity.param.DeviceChannelParam;
import com.topnav.mc.admin.entity.param.DeviceParam;
import com.topnav.mc.admin.security.PermissionGrade;
import com.topnav.mc.admin.service.IDeviceService;
import com.topnav.mc.admin.service.IGbServerService;
import com.topnav.mc.admin.service.IOrganizationService;
import com.topnav.mc.exception.ExceptionMsg;
import com.topnav.mc.position.PositionInfo;
import com.topnav.mc.position.PositionUtil;
import com.topnav.mc.uitls.MapUtil;
import com.topnav.mc.uitls.PermissionGradeUtil;
import com.topnav.mc.uitls.ResultErrorUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.util.*;

/**
 * 提供搜索或懒加载单位及设备
 */
@Service
public class DeviceTreeServiceImpl {
    @Resource
    private PermissionGradeUtil pmGradeUtil;
    @Autowired
    private IOrganizationService organizationService;
    @Autowired
    private IDeviceService deviceService;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private DeviceChannelMapper deviceChannelMapper;
    @Autowired
    private IGbServerService gbServerService;


    /**
     * 统计设备及通道，返回树结构结果集
     * @param pid
     * @return
     */
    public Result findDeviceTree(String pid){
        Result result = null;
        List<OrgDeviceBean> data = new ArrayList<OrgDeviceBean>();

        //当前用户权限
        PermissionGrade permissionGrade = pmGradeUtil.getPmGrade();
        if (permissionGrade == null){
            ResultErrorUtil.byExceptionMsg(ExceptionMsg.ERROR_AUTHENTICATION_FAILE);
        }

        if (StringUtils.isEmpty(pid)){
            result = this.findTopLayer();
            /**
             *  findTopLayer
             *    count
             *    sum
             */
        }else{
            result = this.findDownLayer(pid);
            /**
             * findDownOrg || findDownChn
             *
             */
        }
        return result;
    }

    /**
     * 只加载下一层数据
     * @param pid
     * @return
     */
    private Result findDownLayer(String pid) {
        List<OrgDeviceBean> data = new ArrayList<OrgDeviceBean>();
        String[] pids = pid.split("-");
        if ("O".equals(pids[0])) {
            //查单位下的子单位和设备
            return this.findDownOrg(pids[1]);
        } else if ("D".equals(pids[0])) {
            //查设备下的通道
            return this.findDownChn(pids[1]);
        } else if ("C".equals(pids[0])) {
            return Result.ok(data);
        }
        return Result.ok(data);
    }

    /**
     * 点单编号查询本单位下的设备
     * @param parentId
     * @return
     */
    private Result findDownOrg(String parentId) {
        //查询出子级单位列表
        QueryWrapper<Organization> orgWrapper = new QueryWrapper<>();
        orgWrapper.eq("parent_id", parentId);
        orgWrapper.orderByAsc("path");
        List<Organization> orgList = organizationService.list(orgWrapper);
        //查询出设备
        QueryWrapper<DeviceParam> devWrapper = new QueryWrapper<>();
        devWrapper.eq("d.org_id", parentId);
        devWrapper.eq("d.cate", 2);
        //devWrapper.and(wrapper1->wrapper1.eq("d.type",2).or().eq("d.type",3));
        List<DeviceBean> deviceList = deviceService.listInfo(devWrapper);

        /** 统计 结果集： origId|devieId=（n/n）*/
        Map<String,String> countMap = this.count(Long.valueOf(parentId));

        //汇总结果集
        return this.sum(orgList,deviceList,countMap);
    }

    /**
     * 查设备下的多个通道
     * @param parentId
     * @return
     */
    public Result findDownChn(String parentId) {
        List<OrgDeviceBean> data = new ArrayList<OrgDeviceBean>();
        QueryWrapper<DeviceChannelParam> chnWrapper = new QueryWrapper<>() ;
        chnWrapper.eq("c.device_id",parentId);
        List<DeviceChannelBean> deviceChannelBeanList = deviceChannelMapper.selectInfoList(chnWrapper);
        for(DeviceChannelBean bean:deviceChannelBeanList){
            OrgDeviceBean orgDeviceBean = new OrgDeviceBean();
            orgDeviceBean.setId("C-" + bean.getId());
            orgDeviceBean.setTitle(bean.getName());
            orgDeviceBean.setType("chn");
            orgDeviceBean.setDeviceType(3);
            orgDeviceBean.setOnline(bean.getStatus().toString());
            orgDeviceBean.getArrt().put("code",bean.getChannelCode());
            orgDeviceBean.getArrt().put("deviceCode",bean.getDeviceCode());
            orgDeviceBean.getArrt().put("channelCode",bean.getChannelCode());
            orgDeviceBean.getArrt().put("deviceId",bean.getDeviceId());
            orgDeviceBean.getArrt().put("orgName",bean.getOrgName());
            orgDeviceBean.getArrt().put("orgCode",bean.getOrgCode());
            orgDeviceBean.getArrt().put("orgId",bean.getOrgId());
            orgDeviceBean.getArrt().put("devName",bean.getDeviceName());
            orgDeviceBean.getArrt().put("deviceName",bean.getDeviceName());
            orgDeviceBean.getArrt().put("userName",bean.getUserName());
            orgDeviceBean.getArrt().put("userCode",bean.getUserCode());
            orgDeviceBean.getArrt().put("direction","0°");
            orgDeviceBean.getArrt().put("speed","0.00");
            orgDeviceBean.getArrt().put("locate","");
            orgDeviceBean.getArrt().put("streamEncryption",bean.getStreamEncryption());

            //orgDeviceBean.setChildren(new ArrayList<>());
            data.add(orgDeviceBean);
        }
        return Result.ok(data);
    }

    /**
     * 单位列表，设备列表，离在线统计汇总出结果
     * @param orgList
     * @param deviceList
     * @param countMap
     * @return
     */
    private Result sum(List<Organization> orgList,List<DeviceBean> deviceList ,Map<String,String> countMap){
        List<OrgDeviceBean> OrgDeviceBeans = new ArrayList<OrgDeviceBean>();
        String constStr = "%s %s";//名称 （在线/总量）
        String title = null,orgId=null,deviceId=null;
        Object count="0",onlineCount ="0";
        String online="0";

        //单位部门
        for(Organization organization : orgList){
            OrgDeviceBean orgDeviceBean = new OrgDeviceBean();
            orgId = "O-"+organization.getId().toString();
            title = String.format(constStr,
                    organization.getName(),
                    countMap.get(orgId)==null?"(0/0)":countMap.get(orgId));
            if (countMap.get(orgId)!=null){
                orgDeviceBean.setChildren(new ArrayList<>());
            }
            orgDeviceBean.setId(orgId);
            orgDeviceBean.setTitle(title);
            orgDeviceBean.setType("org");
            orgDeviceBean.setOnline("0");
            orgDeviceBean.getArrt().put("code",organization.getCode());
            OrgDeviceBeans.add(orgDeviceBean);
        }

        //设备
        for(DeviceBean device : deviceList){
            online="0";
            OrgDeviceBean orgDeviceBean = new OrgDeviceBean();
            //if (device.getType() == 2){ //执法仪
            if (device.getChannelCount() == 1){
                //执法仪是执法就不能再点下级，此级就可以播放
                orgId = "C-"+device.getId().toString();
                title = device.getName();
                orgDeviceBean.getArrt().put("deviceCode",device.getCode());
                orgDeviceBean.getArrt().put("channelCode",device.getDefaultChannel());
                orgDeviceBean.setType("chn");
                //执法仪的在线状态
                online = device.getOnline()==null||!device.getOnline()?"0":device.getOnline().toString();
                GbServer gbServer = gbServerService.getFromCache(device.getGbServerId().toString());
            }else if (device.getChannelCount() > 1){ //if (device.getType() == 3)
                //多个通道则需要点击展开
                orgDeviceBean.setType("dev");
                orgId = "D-"+device.getId().toString();
                title = String.format(constStr,
                        device.getName(),
                        countMap.get(orgId)==null?"":countMap.get(orgId));
                orgDeviceBean.setOnline("0");
            }
            if (countMap.get(orgId)!=null){
                orgDeviceBean.setChildren(new ArrayList<>());
            }
            orgDeviceBean.setOnline(online);
            orgDeviceBean.setId(orgId);
            orgDeviceBean.setTitle(title);
            orgDeviceBean.setDeviceType(device.getType());
            orgDeviceBean.getArrt().put("deviceCode",device.getCode());
            //orgDeviceBean.getArrt().put("channelCode",device.);
            orgDeviceBean.getArrt().put("orgName",device.getOrgName());
            orgDeviceBean.getArrt().put("orgCode",device.getOrgCode());
            orgDeviceBean.getArrt().put("orgId",device.getOrgId());
            orgDeviceBean.getArrt().put("devName",device.getName());
            orgDeviceBean.getArrt().put("deviceName",device.getName());
            orgDeviceBean.getArrt().put("userName",device.getUserName());
            orgDeviceBean.getArrt().put("userCode",device.getUserCode());
            orgDeviceBean.getArrt().put("direction","0°");
            orgDeviceBean.getArrt().put("speed","0.00");
            orgDeviceBean.getArrt().put("locate","");
            orgDeviceBean.getArrt().put("streamEncryption",device.getStreamEncryption());
            OrgDeviceBeans.add(orgDeviceBean);
        }
        return Result.ok(OrgDeviceBeans);
    }

    /**
     * 只加载第一层数据
     * @return
     */
    public Result findTopLayer(){

        //当前用户权限
        PermissionGrade permissionGrade = pmGradeUtil.getPmGrade();
        String parentId=permissionGrade.getOrgId()==null?null:permissionGrade.getOrgId().toString();
        QueryWrapper<Organization> orgWrapper = new QueryWrapper<>();
        if (permissionGrade.getPermissionLevel()==1 || permissionGrade.getPermissionLevel()==2){
            orgWrapper.eq("id",permissionGrade.getOrgId());
        }else if (permissionGrade.getPermissionLevel()==3 || permissionGrade.getPermissionLevel()==4){
            orgWrapper.eq("parent_id",permissionGrade.getOrgId())
                    .or()
                    .eq("id",permissionGrade.getOrgId());
        }else if (permissionGrade.getPermissionLevel()==9){
            //部门系统管理员
            orgWrapper.isNull("parent_id");
        }else if ("admin".equals(permissionGrade.getUserName().toLowerCase())){
            //部门系统管理员
            orgWrapper.isNull("parent_id");
        }

        orgWrapper.orderByAsc("path");
        //查询出单位列表
        List<Organization> orgList = organizationService.list(orgWrapper);
        //================================================================================
        List<DeviceBean> deviceList = new ArrayList<>();
        if(permissionGrade.getPermissionLevel()==9){
            //高级系统管理才会看到没有设置单位的设备
            QueryWrapper<DeviceParam> devWrapper = new QueryWrapper<>();
            if (permissionGrade.getPermissionLevel()==1 || permissionGrade.getPermissionLevel()==2){
                devWrapper.eq("d.org_id",permissionGrade.getOrgId());
            }else if (permissionGrade.getPermissionLevel()==3 || permissionGrade.getPermissionLevel() == 4){
                devWrapper.eq("o.parent_id",permissionGrade.getOrgId());
            }else if (permissionGrade.getPermissionLevel()==8){
                //只查第一级单位下的设备
                devWrapper.eq("o.parent_id",permissionGrade.getOrgId());
            }else if(permissionGrade.getPermissionLevel()==9){
                //没有设备单位的
                devWrapper.isNull("d.org_id");
            }
            // QueryWrapper Or嵌套用法
            devWrapper.and(wrapper1->wrapper1.eq("d.cate",2));///.or().eq("d.type",3));
            QueryWrapper<DeviceChannelParam> chnWrapper = null;
            //查询出当前单位下的设备列表
            deviceList = deviceService.listInfo(devWrapper);
        }



        Map<String,String> countMap = null;
        /** 统计 结果集： origId|devieId=（n/n）*/
        if (parentId != null){
            //统计每个部门下的设备数量
            countMap = this.count(Long.valueOf(parentId));
        }else{
            //统计每个部门下的设备数量
            countMap = this.count(null);
        }
        //System.out.println(countMap.toString());

        //汇总结果集
        return this.sum(orgList,deviceList,countMap);
    }

    /**
     * 通道统计
     * @param parentId
     * @return  origId|devieId=（n/n）
     */
    private Map<String,String> count(Long parentId){
        String constStr = "(%s/%s)";
        String quantity = null;

        Map<String,String> resultMap = new HashMap<>();
        //统计所有通道 Map.key=orgId 或 deviceId; Map.Value=通道总数
        Map<String,Integer> channelCount = this.deviceCountByOrg(parentId);
        //查询所有在线通道
        Map<String,Integer> onLineCount = this.onLineDeviceCount(parentId);

        for(Map.Entry<String,Integer> e: channelCount.entrySet()){
            quantity = String.format(
                    constStr,
                    onLineCount.get(e.getKey())==null?"0":onLineCount.get(e.getKey()).toString(),
                    e.getValue() == null?"0":e.getValue().toString());
            resultMap.put(e.getKey(),quantity);
        }
        return resultMap;
    }


    /**
     * 统计每个单位的设备数
     * @param parentId 输入单位ID或设备ID
     * @return Map.key=orgId 或 deviceId; Map.Value=通道总数
     */
    private Map<String,Integer> deviceCountByOrg(Long parentId){
        QueryWrapper<DeviceChannel> devChnWrapper = new QueryWrapper();
        if (parentId == null){
            //第一层
            PermissionGrade permissionGrade = pmGradeUtil.getPmGrade();
            if (permissionGrade.getPermissionLevel()<=4){
                devChnWrapper.likeRight("o.path",permissionGrade.getOrgPath());
            }
        }else{
            Organization organization = organizationService.getById(parentId);
            devChnWrapper.likeRight("o.path",organization.getPath());
         }
        devChnWrapper.isNotNull("d.org_id");
        //devChnWrapper.and(wrapper1->wrapper1.eq("d.type",2).or().eq("d.type",3));
        devChnWrapper.and(wrapper1->wrapper1.eq("d.cate",2));
        devChnWrapper.and(wrapper1->wrapper1.eq("c.channel_type",1)); //只取视频通道
        //结果集 orgId,deviceId,channelCount,orgCode,path,type
        //List<Map<String,Object>> channels = deviceChannelMapper.countChannel(devChnWrapper);
        List<CountChannelBean> channels = deviceChannelMapper.countChannel(devChnWrapper);


        //累加
        Map<String,Integer> allMap =  this.sumCount(channels);
        return allMap;
    }

    /**
     * 统计在线设备数量
     * @param parentId
     * @return
     */
    private Map<String,Integer> onLineDeviceCount(Long parentId){
        QueryWrapper<DeviceChannel> devChnWrapper = new QueryWrapper();
        //设备必须在线
        devChnWrapper.eq("d.`online`",1);
        devChnWrapper.eq("d.`cate`",2);
        devChnWrapper.eq("c.`channel_type`",1);
        //查在线的
        //(d.type = 2 and d.online=false) or (c.status=1)
        devChnWrapper.and(
                //有些执法传上来的通道status为0
                wrapper1->wrapper1.and(wrapper2->wrapper2.eq("d.channel_count",1).eq("c.status",0))
                        .or(wrapper3->wrapper3.eq("c.status",1))
        );
        //结果集 orgId,path,deviceId,channelCount,channelId,type
        List<CountChannelBean> onlineChannels = deviceChannelMapper.countChannel(devChnWrapper);


        Map<String,Integer> allMap =  this.sumCount(onlineChannels);

        return allMap;
    }



    /**
     * 统计结果汇总
     * 下级向上级汇总
     * @param channelCounts 按单位设备编号统计
     * @return  Map.key=orgId 或 deviceId; Map.Value=通道总数
     */
    //private Map<String,Integer> sumCount(List<Map<String,Object>> channelCounts){
    private Map<String,Integer> sumCount(List<CountChannelBean> channelCounts){

        //orgId,deviceId,channelCount,orgCode,path
        Map<String,Integer> allMap = new HashMap<>();
        String[] paths=null;
        Integer totalAll = 0;
        Integer type = 2;
        int channelCount = 1;
        String newOrgId=null;
        //Integer channelCount1 = 0;
        for(CountChannelBean countChannelBean : channelCounts){

            if (countChannelBean.getChannelCount() > 1){
                //一个设备下有多个通道
                newOrgId = "D-" + countChannelBean.getDeviceId().toString();
                totalAll=allMap.get(newOrgId);
                totalAll= totalAll == null?1:totalAll+1;
                allMap.put(newOrgId, totalAll);
            }
            if (!StringUtils.isEmpty(countChannelBean.getPath())){
                paths = countChannelBean.getPath().split("/");
                for(int i=paths.length-1;i>=0;i--){
                    // 设备总数
                    newOrgId = "O-" + paths[i];
                    totalAll=allMap.get(newOrgId);
                    totalAll= totalAll == null?1:totalAll+1;
                    allMap.put(newOrgId, totalAll);
                }
            }

/*
            if (type == 3){
                //一个设备下有多个通道
                newOrgId = "D-" + map.get("deviceId").toString();
                totalAll=allMap.get(newOrgId);
                totalAll= totalAll == null?1:totalAll+1;
                allMap.put(newOrgId, totalAll);
            }


            if (!StringUtils.isEmpty(map.get("path"))){
                paths = ((String)map.get("path")).split("/");
                for(int i=paths.length-1;i>=0;i--){
                    // 设备总数
                    newOrgId = "O-" + paths[i];
                    totalAll=allMap.get(newOrgId);
                    totalAll= totalAll == null?1:totalAll+1;
                    allMap.put(newOrgId, totalAll);
                }
            }
            */
        }
        //System.err.println("sumCount.allMap: ");
        //System.err.println(allMap);
        return allMap;
    }




    public class collectDevice{

    }



}
